//////////////////////////////////////////////
// InputSystem.h
//
//////////////////////////////////////////////

/// Defines / Macros -------------------------

#pragma once

/// Forward decl -----------------------------

namespace nkMaths
{
	class Point ;
}

namespace nkWinUi
{
	class Component ;
	class System ;

	struct ClickEventData ;
	struct KeyEventData ;
	struct WheelEventData ;
}

/// Includes ---------------------------------

// nkWinUi
#include "../Dll/DllDefines.h"

#include "EventTypes.h"

// Common
#include <nilkinsCommon/Patterns/MaybeSingletonClass.h>

// Standards
#include <functional>
#include <unordered_map>
#include <vector>

/// Class ------------------------------------

namespace nkWinUi
{
	class DLL_WINUI_EXPORT InputSystem final : public nkCommon::MaybeSingletonClass<InputSystem>
	{		
		public :			

			// Tracking requests
			void registerToTrack (EVENT_TYPE eventType, Component* component) ;
			void unregisterTracking (EVENT_TYPE eventType, Component* component) ;
			void requestWindowFollow (Component* caller, bool value) ;

			// Getters
			std::function<bool (Component*)> getCloseCallback () const ;
			std::function<void (Component*, bool)> getVisibilityCallback () const ;
			std::function<void (Component*, const ClickEventData&)> getClickCallback () const ;
			std::function<void (Component*, const WheelEventData&)> getWheelCallback () const ;
			std::function<void (Component*, const KeyEventData&)> getKeyCallback () const ;

			const std::unordered_map<Component*, std::pair<bool, bool>>& getFollowedWindows () const ;

			// Setters
			void setCloseCallback (std::function<bool (Component* caller)> callback) ;
			void setVisibilityCallback (std::function<void (Component* caller, bool visibility)> callback) ;
			void setClickCallback (std::function<void (Component* caller, const ClickEventData& eventData)> callback) ;
			void setWheelCallback (std::function<void (Component* caller, const WheelEventData& eventData)> callback) ;
			void setKeyCallback (std::function<void (Component* caller, const KeyEventData& eventData)> callback) ;

		private :
		
			// Functions
			// Constructor, destructor
			InputSystem (bool isSingleton) noexcept ;
			InputSystem (System* parentSystem) noexcept ;

		private :

			// Attributes
			// Callbacks
			std::function<bool (Component*)> _closeCallback ;
			std::function<void (Component*, bool)> _visibilityCallback ;
			std::function<void (Component*, const ClickEventData&)> _clickCallback ;
			std::function<void (Component*, const WheelEventData&)> _wheelCallback ;
			std::function<void (Component*, const KeyEventData&)> _keyCallback ;

			// Components asking for events even if not focused
			std::unordered_map<EVENT_TYPE, std::vector<Component*>> _trackedComponents ;

			// Memory of followed windows for mouse leave events
			std::unordered_map<Component*, std::pair<bool, bool>> _followedWindows ;

			// Parent
			System* _parentSystem ;

		private :

			friend class nkCommon::MaybeSingletonClass<InputSystem> ;
			friend class System ;
	} ;
}